package com.kitty.game.difushidao.service;

import com.kitty.common.cache.RedisService;
import com.kitty.common.utils.SpringUtils;
import com.kitty.common.utils.ConcurrentHashSet;
import com.kitty.common.core.SchedulerManager;
import com.kitty.game.activity.model.user.ShiDaoData;
import com.kitty.game.chat.service.ChatService;
import com.kitty.game.config.NPC;
import com.kitty.game.difushidao.controller.DiFuShiDaoController;
import com.kitty.game.difushidao.domin.DiFuShiDaoPKData;
import com.kitty.game.difushidao.domin.TeamData;
import com.kitty.game.enter.ReqTelePort;
import com.kitty.game.equip.message.RespNotifyMiscEx;
import com.kitty.game.mail.model.Mail;
import com.kitty.game.map.MapDataPool;
import com.kitty.game.map.model.GroupMapParam;
import com.kitty.game.rank.model.Range;
import com.kitty.game.role.model.Role;
import com.kitty.game.team.model.Member;
import com.kitty.game.team.model.Team;
import com.kitty.game.team.service.TeamService;
import com.kitty.game.utils.Const;
import com.kitty.game.utils.TimeUtil;
import com.kitty.mina.cache.DataCache;
import com.kitty.mina.message.MessagePusher;
import com.kitty.mina.task.ThreadLocalUtil;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.nutz.json.Json;
import org.nutz.json.JsonFormat;
import org.nutz.lang.util.NutMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.text.MessageFormat;
import java.util.*;
import java.util.function.Consumer;

@Service
@Slf4j
public class DiFuShiDaoService {
    private int startH = 20;
    private int startM = 50;
    private int MAPID = 60007;
    private int MAP_X = 41;
    private int MAP_Y = 31;


    private static final int EXIT_MAPID = 60000;
    private static final int EXIT_X = 130;
    private static final int EXIT_Y = 40;
    private static final String ACCEPT_JOIN_LIMIT = "该地图无法操作申请队员";
    private static final String FIGHT_LEVEL_NOT_ENOUGH = "等级达到70级方可参加地府竞技大赛。[离开]";
    private static final String NOT_SIGNUP_TIME = "现在还不是报名时间，#Y{0}#n级别地府竞技大赛下一场将于#R{1}#n开始报名。[离开]";
    private static final String TIME_FORMAT_PATTERN = "yyyy-MM-dd";
    private static final String SIGNUP_END = "地府竞技大赛已经开始，不可报名参加[离开]";
    private static final String LEVEL_NOT_SAME = "#Y{0}#n的等级不符，无法参加#Y{1}#n级别的地府竞技大赛。[离开]";
    private static final String MEMBER_LEAVE_MONMENT = "#Y{0}#n暂离，无法参加地府竞技大赛。[离开]";
    private static final String TEAM_COUNT_NOT_ENOUGH = "参加地府竞技大赛活动#Y最大队伍人数#n不符合，请调整！！[离开]";
    /**
     * 等级段
     */
    private static  List<Range<Short>> levelRanges = new ArrayList<>();
    /**key: teamId, value: 对应的试道队伍pk阶段数据*/

    @Getter
    @Setter
    public static ShiDaoData shiDaoData;
    @Autowired
    ChatService chatService;
    @Autowired
    DiFuShiDaoPKService diFuShiDaoPKService;
    @Autowired
    TeamService teamService;
    @Autowired
    RedisService redisService;

    @PostConstruct
    public void init() {
        MapDataPool.MAP_KEY_GENERATERS.put(Const.DIFU_SHIDAO_MAPID, (role -> getLevelRange(role)));
        initRange();
    }

    /**
     * 初始化等级段
     */
    private void initRange() {
        levelRanges.add(new Range((short) 70, (short) 79));
        levelRanges.add(new Range((short) 80, (short) 89));
        levelRanges.add(new Range((short) 90, (short) 99));
        levelRanges.add(new Range((short) 100, (short) 109));
        levelRanges.add(new Range((short) 110, (short) 119));
        levelRanges.add(new Range((short) 120, (short) 129));
        levelRanges.add(new Range((short) 130, (short) 139));
        levelRanges.add(new Range((short) 140, (short) 149));
        levelRanges.add(new Range((short) 150, (short) 159));
        levelRanges.add(new Range((short) 160, (short) 169));
        levelRanges.add(new Range((short) 170, (short) 179));
    }

//    public void notifyShidao() {
//        prepareOnceShiDao();
//        SchedulerManager.getInstance().schedule(new Runnable() {
//            @Override
//            public void run() {
//                String notice = "本次试道大会将于#R晚上19:50开启#n，恭候各位道友准时降临试道场！#51 #82";
//                chatService.sendAdnotice(notice);
//            }
//        }, 30000);
//        for (int i = 0; i < 11; i++) {
//            SchedulerManager.getInstance().schedule(new Runnable() {
//                @Override
//                public void run() {
//                    String notice = "本次试道大会将于#R晚上19:50开启#n，恭候各位道友准时降临试道场！#51 #82";
//                    chatService.sendAdnotice(notice);
//                }
//            }, 60000 * (i + 1) * 5);
//        }
//    }

    /**
     * 初始化试道大会数据
     */
    private void initShiDaoData() {
        //清楚所有等级段的人
        rangeHandle(levelRange -> clear(levelRange));
        //清楚所有匹配队列的人
        DiFuShiDaoController.piPeiQueByLevel.clear();
        //清除所有角色在地府竞技场中的 临时
        DiFuShiDaoPKService.pkRoleinfo.clear();
        //表示可以进场

        DataCache.REDIS_DATA.put("difushidao_status","1");
        ShiDaoData shiDaoData = new ShiDaoData();
        initTime(shiDaoData);
        int perpareTimeH = shiDaoData.getSignupTime().get(Calendar.HOUR_OF_DAY);
        int perpareTimeM = shiDaoData.getSignupTime().get(Calendar.MINUTE);
        int startTimeH = shiDaoData.getStartTime().get(Calendar.HOUR_OF_DAY);
        int startTimeM = shiDaoData.getStartTime().get(Calendar.MINUTE);
        String notice = "本次地府竞技大赛将于#R"+perpareTimeH+":"+perpareTimeM+"#n开启报名#R"+startTimeH+":"+startTimeM+"#n开始正式竞赛，各位道友准时前往地府阎罗王处报名参加，竞技场准备期间请不要离队，离队会被直接传送出去！#51 #82";
        chatService.sendAdnotice(notice);
        this.shiDaoData = shiDaoData;
    }

    public void rangeHandle(Consumer<String> consumer) {
        for (Range<Short> range : levelRanges) {
            String levelRange = getLevelRange(range);
            consumer.accept(levelRange);
        }
    }
    /**
     * 找到角色对应的分段
     */
    public static String getLevelRange(Role role) {
        short roleLevel = role.getLevel();
        Range<Short> range = getRange(roleLevel);
        if (range != null) {
            return getLevelRange(range);
        }
        return null;
    }
    public static Range getRange(short roleLevel) {
        for (Range<Short> range : levelRanges) {
            if (roleLevel >= range.getMin() && roleLevel <= range.getMax()) {
                return range;
            }
        }
        return null;
    }
    public static String getLevelRange(Range range) {
        return range.getMin() + "-" + range.getMax();
    }
    private void clear(String levelRange) {
        ConcurrentHashSet<Integer> roleIds = SpringUtils.getMapService().getRoleIds(new GroupMapParam(levelRange), Const.SHIDAO_MAPID);
        if (roleIds != null) {
            log.error("上次试道遗留的角色ID信息=={}=={}", levelRange, Json.toJson(roleIds, JsonFormat.compact()));
            roleIds.clear();
        }
    }
    /**
     * 初始化时间
     */
    public void initTime(ShiDaoData shiDaoData) {
        Calendar calendarStart = Calendar.getInstance();
        calendarStart.setTime(new Date());
        shiDaoData.setSignupTime(get(calendarStart));
        //10分钟报名时间
        String difushidao_perparetime = DataCache.REDIS_DATA.get("difushidao_perparetime").toString();
        calendarStart.add(Calendar.MINUTE, Integer.parseInt(difushidao_perparetime));
        shiDaoData.setStartTime(get(calendarStart));
        //PK时间
        String difushidao_fighttime = DataCache.REDIS_DATA.get("difushidao_fighttime").toString();
        calendarStart.add(Calendar.MINUTE, Integer.parseInt(difushidao_fighttime));
        shiDaoData.setEndTime(get(calendarStart));

        /**月道行试道大会*/

        shiDaoData.setMonthTao(true);
        int time = (int) (shiDaoData.getEndTime().getTimeInMillis() / TimeUtil.ONE_SECOND);
        if (!DataCache.MONTH_SHI_DAO_TIMES.contains(time)) {
            DataCache.MONTH_SHI_DAO_TIMES.add(time);
        }
        log.info("初始化地府竞技大赛|报名时间:{}, 开始时间:{},  整个结束时间:{}, 月道行试道大会:{}",
                TimeUtil.formatDate(shiDaoData.getSignupTime().getTime(), TimeUtil.DEFAULT_DATE_FORMAT),
                TimeUtil.formatDate(shiDaoData.getStartTime().getTime(), TimeUtil.DEFAULT_DATE_FORMAT),
                TimeUtil.formatDate(shiDaoData.getEndTime().getTime(), TimeUtil.DEFAULT_DATE_FORMAT),
                true);
    }
    private Calendar get(Calendar calendarStart) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(calendarStart.getTime());
        calendar.set(Calendar.HOUR_OF_DAY, calendarStart.get(Calendar.HOUR_OF_DAY));
        calendar.set(Calendar.MINUTE, calendarStart.get(Calendar.MINUTE));
        calendar.set(Calendar.SECOND, 0);
        return calendar;
    }
    /**
     * 为试道大会做准备工作
     */
    public void prepareOnceShiDao() {
        initShiDaoData();
        addStartJob();
        addEndJob();
    }

    /**
     * 添加地府试道大会开始的定时任务
     */
    private void addStartJob() {
        long initialDelay = shiDaoData.getStartTime().getTimeInMillis() - System.currentTimeMillis();
        log.info("添加地府试道大会开始的定时任务==={}", initialDelay);
        SchedulerManager.getInstance().schedule(() -> SpringUtils.getBean(DiFuShiDaoPKService.class).start(), initialDelay);
    }
    /**
     * 添加地府试道大会结束的定时任务
     */
    private void addEndJob() {
        long initialDelay = shiDaoData.getEndTime().getTimeInMillis() - System.currentTimeMillis();
        log.info("添加地府试道大会结束的定时任务==={}", initialDelay);
        SchedulerManager.getInstance().schedule(() -> SpringUtils.getBean(DiFuShiDaoPKService.class).end(), initialDelay);
    }


    /**
     * 进入地府竞技大赛地图
     */
    public void enterDIFUShiDaoMap(Role role, NPC bossNpc) {
         String content = canEnter(role);
        if (content != null) {
            SpringUtils.getNpcService().sendNpcContent(role, bossNpc, content);
            return;
        }
        this.doEnterShiDaoMap(role);
    }

    /**
     * 进入地府试道大会地图
     */
    public void doEnterShiDaoMap(Role role) {
        ReqTelePort reqTelePort = new ReqTelePort();
        reqTelePort.setMapId(Const.DIFU_SHIDAO_MAPID);
        reqTelePort.setX(MAP_X);
        reqTelePort.setY(MAP_Y);
        SpringUtils.getMapService().changeMap(role, reqTelePort);
        Team team = teamService.getTeam(role.getRoleId());

        if(team == null){
          //不组队禁止进入竞技场.
        }else{
            for (Member member : team.getList()) {
                Role memberRole = SpringUtils.getRoleService().getOnlinePlayer(member.getRoleId());
                DiFuShiDaoPKData diFuShiDaoPKData = new DiFuShiDaoPKData();
                diFuShiDaoPKData.setRoleId(member.getRoleId());
                DiFuShiDaoPKService.pkRoleinfo.put(memberRole.getRoleId(),diFuShiDaoPKData);
                /**需要在进入地图后发送，所以加到玩家的处理线程最后*/
                ThreadLocalUtil.addLocalTask(memberRole, () -> diFuShiDaoPKService.sendRespShidaoScore(memberRole,0));
                log.info("进入地府试道场=={}=={}", memberRole.getGid(), memberRole.getName());
            }
        }
    }
    /**
     * 离开地府竞技大赛地图
     */
    public void exitDIFUShiDaoMap(Role role, NPC bossNpc) {
        this.leaveDiFuShiDaoMap(role);
    }



    /**
     * 离开试道大会地图
     */
    public void leaveDiFuShiDaoMap(Role role) {
        if (role == null) {
            return;
        }
        /**不在试道大会地图不处理*/
        if (role.getPos().getMapId() != Const.DIFU_SHIDAO_MAPID) {
            return;
        }
        /**不需要检测能否切换地图*/
        role.pushTempCache(Const.NOT_CHECK_CHANGE_MAP, true);

        ReqTelePort reqTelePort = new ReqTelePort();
        reqTelePort.setMapId(EXIT_MAPID);
        reqTelePort.setX(EXIT_X);
        reqTelePort.setY(EXIT_Y);
        SpringUtils.getMapService().changeMap(role, reqTelePort);


        //移除匹配队列
        String levelRange = this.getLevelRange(role);
        Set<Team> teams = DiFuShiDaoController.piPeiQueByLevel.get(levelRange);
        Team team = teamService.getTeam(role.getRoleId());
        if(teams != null && team != null){
            teams.remove(team);
        }
        //移除试道大会 角色临时对象
       if(team != null){
           for (Member member : team.getList()) {
               //DiFuShiDaoPKData diFuShiDaoPKData = DiFuShiDaoPKService.pkRoleinfo.get(member.getRoleId());
               //sendDiFuShiDaoReward(diFuShiDaoPKData);
               DiFuShiDaoPKService.pkRoleinfo.remove(member.getRoleId());
           }
       }else{
           //DiFuShiDaoPKData diFuShiDaoPKData = DiFuShiDaoPKService.pkRoleinfo.get(role.getRoleId());
           //sendDiFuShiDaoReward(diFuShiDaoPKData);
           DiFuShiDaoPKService.pkRoleinfo.remove(role.getRoleId());
       }
    }




    public String canEnter(Role role) {
        /**等级不足*/
        if (role.getLevel() < 70) {
            return FIGHT_LEVEL_NOT_ENOUGH;
        }

        String levelRange = getLevelRange(role);
        Calendar calendar = Calendar.getInstance();
        String difushidao_status = DataCache.REDIS_DATA.get("difushidao_status").toString();
        if("0".equals(difushidao_status)){
            return "地府竞技大赛还未开始！[离开]";
        }
        /**试道大会已经开始*/
        if("2".equals(difushidao_status)){
            return SIGNUP_END;
        }
        if(!teamService.isInTeam(role)){
            return "请组队进入赛场！[离开]";
        }
        /**人数不能多余X人*/
        int teamCount = teamService.getTeamCount(role);
        int minTeamMembetCount = Integer.parseInt(DataCache.REDIS_DATA.get("difushidao_minteam_count"));
        if (teamCount > minTeamMembetCount) {
            MessagePusher.pushMessage(role, new RespNotifyMiscEx("#Y报名地府竞技大赛队伍人数最多为#n #R"+minTeamMembetCount+"#n #Y人，请减少人数至 #R"+minTeamMembetCount+"#n #Y人，或以下再报名参加"));
            return TEAM_COUNT_NOT_ENOUGH;
        }

        /**队员等级段是否相同*/
        Team team = teamService.getTeam(role.getRoleId());
        if(team != null){
            String names = teamService.checkMember(team, memberRole -> !levelRange.equals(getLevelRange(memberRole)));
            if (names != null) {
                return MessageFormat.format(LEVEL_NOT_SAME, names, levelRange);
            }
            names = teamService.getNotInTeam(team);
            if (names != null) {
                return MessageFormat.format(MEMBER_LEAVE_MONMENT, names, levelRange);
            }
        }
        return null;
    }

    public boolean isAcceptJoinTeam(Role role, int joinRoleId) {

        Role joinRole = SpringUtils.getRoleService().getOnlinePlayer(joinRoleId);
        //两个人有人在地府竞技场内,不允许组队
        if(diFuShiDaoPKService.isInDiFuShiDaoMap(role) || diFuShiDaoPKService.isInDiFuShiDaoMap(joinRole)){
            return false;
        }
        if (diFuShiDaoPKService.isInDiFuShiDaoMap(role)) {
            MessagePusher.pushMessage(role, new RespNotifyMiscEx(ACCEPT_JOIN_LIMIT));
            return false;
        }

        if (diFuShiDaoPKService.isInDiFuShiDaoMap(joinRole)) {
            MessagePusher.pushMessage(role, new RespNotifyMiscEx(ACCEPT_JOIN_LIMIT));
            return false;
        }

        return true;
    }
    /**
     * 是否可以切磋竞技
     */
    private static final String COMPETE_PK_LIMIT = "你现在不能与人切磋。";
    public boolean isCompetePK(Role role, Role pkRole) {
        if (diFuShiDaoPKService.isInDiFuShiDaoMap(role)) {
            MessagePusher.pushMessage(role, new RespNotifyMiscEx(COMPETE_PK_LIMIT));
            return false;
        }

        if (diFuShiDaoPKService.isInDiFuShiDaoMap(pkRole)) {
            MessagePusher.pushMessage(role, new RespNotifyMiscEx(COMPETE_PK_LIMIT));
            return false;
        }

        return true;
    }
}
